package com.mes.cloud.commons;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Enumeration;

/**
 * 请求工具类
 */
public class RequestUtils {

    private static final Logger LOGGER = LoggerFactory.getLogger(RequestUtils.class);
    // 没有可用的请求
    private static final String NON_HTTP_REQ_MSG = "Not available. Non-http request.";
    // 无可用的响应
    private static final String NON_HTTP_RES_MSG = "Not available. Non-http response.";

    private static StringBuilder doDump(ServletRequest request, ServletResponse response) {
        HttpServletRequest hRequest = null;
        HttpServletResponse hResponse = null;

        if (request instanceof HttpServletRequest) {
            hRequest = (HttpServletRequest) request;
        }
        if (response instanceof HttpServletResponse) {
            hResponse = (HttpServletResponse) response;
        }

        StringBuilder sb = new StringBuilder(80);

        dump(sb, "------------------", "--------------------------------------------");
        dump(sb, "REQUEST TIME        ", getTimestamp());

        if (hRequest == null) {
            dump(sb, "        requestURI", NON_HTTP_REQ_MSG);
            dump(sb, "          authType", NON_HTTP_REQ_MSG);
        } else {
            dump(sb, "        requestURI", hRequest.getRequestURI());
            dump(sb, "          authType", hRequest.getAuthType());
        }

        dump(sb, " characterEncoding", request.getCharacterEncoding());
        dump(sb, "     contentLength", Integer.toString(request.getContentLength()));
        dump(sb, "       contentType", request.getContentType());

        if (hRequest == null) {
            dump(sb, "       contextPath", NON_HTTP_REQ_MSG);
            dump(sb, "            cookie", NON_HTTP_REQ_MSG);
            dump(sb, "            header", NON_HTTP_REQ_MSG);
        } else {
            dump(sb, "       contextPath", hRequest.getContextPath());
            Cookie cookies[] = hRequest.getCookies();
            if (cookies != null) {
                for (int i = 0; i < cookies.length; i++) {
                    dump(sb, "            cookie", cookies[i].getName() + "=" + cookies[i].getValue());
                }
            }
            Enumeration<String> hnames = hRequest.getHeaderNames();
            while (hnames.hasMoreElements()) {
                String hname = hnames.nextElement();
                Enumeration<String> hvalues = hRequest.getHeaders(hname);
                while (hvalues.hasMoreElements()) {
                    String hvalue = hvalues.nextElement();
                    dump(sb, "            header", hname + "=" + hvalue);
                }
            }
        }

        dump(sb, "            locale", request.getLocale().toString());

        if (hRequest == null) {
            dump(sb, "            method", NON_HTTP_REQ_MSG);
        } else {
            dump(sb, "            method", hRequest.getMethod());
        }

        Enumeration<String> pnames = request.getParameterNames();
        while (pnames.hasMoreElements()) {
            String pname = pnames.nextElement();
            String pvalues[] = request.getParameterValues(pname);
            StringBuilder result = new StringBuilder(pname);
            result.append('=');
            for (int i = 0; i < pvalues.length; i++) {
                if (i > 0) {
                    result.append(", ");
                }
                result.append(pvalues[i]);
            }
            dump(sb, "         parameter", result.toString());
        }

        if (hRequest == null) {
            dump(sb, "          pathInfo", NON_HTTP_REQ_MSG);
        } else {
            dump(sb, "          pathInfo", hRequest.getPathInfo());
        }

        dump(sb, "          protocol", request.getProtocol());

        if (hRequest == null) {
            dump(sb, "       queryString", NON_HTTP_REQ_MSG);
        } else {
            dump(sb, "       queryString", hRequest.getQueryString());
        }

        dump(sb, "        remoteAddr", request.getRemoteAddr());
        dump(sb, "        remoteHost", request.getRemoteHost());

        if (hRequest == null) {
            dump(sb, "        remoteUser", NON_HTTP_REQ_MSG);
            dump(sb, "requestedSessionId", NON_HTTP_REQ_MSG);
        } else {
            dump(sb, "        remoteUser", hRequest.getRemoteUser());
            dump(sb, "requestedSessionId", hRequest.getRequestedSessionId());
        }

        dump(sb, "            scheme", request.getScheme());
        dump(sb, "        serverName", request.getServerName());
        dump(sb, "        serverPort", Integer.toString(request.getServerPort()));

        if (hRequest == null) {
            dump(sb, "       servletPath", NON_HTTP_REQ_MSG);
        } else {
            dump(sb, "       servletPath", hRequest.getServletPath());
        }

        dump(sb, "          isSecure", Boolean.valueOf(request.isSecure()).toString());


        // Log post-service information
        dump(sb, "------------------", "--------------------------------------------");
        if (hRequest == null) {
            dump(sb, "          authType", NON_HTTP_REQ_MSG);
        } else {
            dump(sb, "          authType", hRequest.getAuthType());
        }

        dump(sb, "       contentType", response.getContentType());

        if (hResponse == null) {
            dump(sb, "            header", NON_HTTP_RES_MSG);
        } else {
            Iterable<String> rhnames = hResponse.getHeaderNames();
            for (String rhname : rhnames) {
                Iterable<String> rhvalues = hResponse.getHeaders(rhname);
                for (String rhvalue : rhvalues) {
                    dump(sb, "            header", rhname + "=" + rhvalue);
                }
            }
        }

        if (hRequest == null) {
            dump(sb, "        remoteUser", NON_HTTP_REQ_MSG);
        } else {
            dump(sb, "        remoteUser", hRequest.getRemoteUser());
        }

        if (hResponse == null) {
            dump(sb, "        remoteUser", NON_HTTP_RES_MSG);
        } else {
            dump(sb, "            status", Integer.toString(hResponse.getStatus()));
        }

        dump(sb, "==================", "============================================");


        return sb;
    }

    public static StringBuilder dumpRequest(ServletRequest request, ServletResponse response) {
        try {
            return doDump(request, response);
        } catch (Throwable e) {
            LOGGER.error(e.getMessage(), e);
            return new StringBuilder();
        }
    }

    public static StringBuilder dumpRequest(HttpServletRequest request, HttpServletResponse response) {
        return dumpRequest((ServletRequest)request, (ServletResponse)response);
    }

    private static void dump(StringBuilder sb, String attribute, String value) {
        sb.append(' ');
        sb.append(attribute);
        sb.append('=');
        sb.append(value);
        sb.append("\r\n");
    }

    private static String getTimestamp() {
        return Constants.DateTimeFormat.DATE_TIME_FORMAT.get().format(CommonUtil.getTimestamp());
    }


}
